<!DOCTYPE html>
<html lang = "en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width-device width,user scalable-no,initial scale=1.0,maximum-scale=l.0,minimum scale=l.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Title</title>


    <script>
        //ES6的入门
        //==================================================
        //let 和 const
        //let用于变量
        let a = 15;
        console.log(a);

        //const用于常量,不可变
        const aa = 15;
        console.log(aa);

        //案例let/const与var的案例展示
        //let可以限定作用域
        window.onload=function(){
            let btn = document.getElementsByTagName('input');
            for (let index = 0; index < btn.length; index++) {
                //for (var index = 0; index < btn.length; index++) {
                //如果使用var会导致3个btn都弹出3,因为循环是异步,先进行循环再执行按钮点击事件
                //而var的作用域是函数级(let和const是块级)
                //最后导致var index变为函数级变量,后续执行点击后调用的是全局变量index

                btn[index].onclick=function(){
                    alert(index);
                }
            }
        };

        //总节,let/const作用域在{}之间,而var是整个函数

        {
            let a = 1;  //与外部的变量a并不冲突
        }


        //==================================================
        //解构赋值,需要满足3个条件
        //1.两边的结构必须相同
        //错误示范,左边是对象,右边是数组
        let {a1,b1} =[1,2];
        console.log(a1,b1); //结果:undefined undefined

        let [aa1,bb1] =[1,2];
        console.log(aa1,bb1); //结果:1 2

        //2.右边必须是一个东西(对象)
        //let {a2,b2} ={1,2};   //直接编译报错,右边不是个东西
        let {a2,b2} = {a2: 1,b2 :2};
        console.log(a2,b2); //结果1 2

        //3.赋值和解构必须同时完成
        //也是编译报错
        //let {a,b};
        //{a,b} = {a:1,b:2};



        //==================================================
        //箭头函数(匿名函数)
        //()=>{}
        window.onload = ()=> {
            alert('111')
        };

        //如果只有一个参数,()可以省略
        //如果只有一个返回,{}也可以省
        let arr = [1,5,10,2,4,8];
        //arr.sort(function(n1,n2){
        arr.sort((n1,n2)=>{ //内置的sort,返回小于等于0则不交换位置;有点java8的像接口方法
            return n1-n2;
        });
        alert(arr);


        //箭头函数和this的结合
        //关于this
        //全局环境的this就是window
        console.log(this === window); // true
        this.a = 37;
        console.log(window.a); // 37
        //在函数中,非严格模式下this指window,严格下为undefined(演示略)
        //在对象中,则指向调用该方法的对象;1.this的指向只和调用函数的对象有关 2.多层嵌套的环境中,this指向最近被调用的函数

        //当箭头函数和this一起使用时,可以对this进行固定的作用(但es5中新出来bind也可以做到该效果)
        //错误的示范
        let json1 = {
            a: 12,
            func: ()=>{
                alert(this.a);
            }
        };
        json1.func();    //undefined
        //因为此处this指向的是全局环境中的window,window下没有a,因此是undefined

        //正确的示范(class之后讲)
        class Json {
            constructor(){      //定义构造函数
                console.log(this);      //这里的this
                this.a =  1;
                this.show = ()=>{
                    console.log(this);  //和这里的this都是同一个,即Json{...}
                    alert(this.a)
                }
                //在此处将show方法通过箭头函数声明,此处的show方法即就被固定到当前环境中,不通过特殊方法无法进行改变
            }
        }

        let json2= new Json();
        json2.show();
        //==================================================
        //参数展开,数组展开,json展开  ...args
        //和java的...args类似;      args必须是最后一个;        args的名称可以自定义

        //一个累加的函数
        function sum(...args){
            let sum = 0;
            args.forEach(element => {
                alert(sum += element);
            });
        }
        sum(1,2,3,4,5);

        //2个数组的合并
        let arr1 = [1,2,3];
        let arr2 = [4,5,6];
        let arrAll = [...arr1,...arr2];
        console.log(arrAll);

        //json的展开
        let json3 = {
            a:1,
            b:2,
            c:3
        };
        let json4 = {
            ...json3,
            d:4
        };
        console.log(json4);


        //==================================================
        //默认参数的设定方法
        function showDefaultParam(a,b=2,c=3){
            alert(a);
            alert(b);
            alert(c);
        }
        showDefaultParam(1);



        //==================================================
        //es6中对原生对象的扩展 map,reduce,filter,forEach
        let arr3 = [1,2,3,4,5]; //实验对象

        //1.map,描述对象的映射关系
        //原始的写法
        let arr3map1 = arr3.map(function (item) {   //此处map中的参数即回调函数
            if (item >= 3) return '及格';
            else return '不及格';
        });
        console.log(1,arr3map1);

        //三元+箭头的写法
        let arr3map2 = arr3.map(item => item >= 3 ? '及格':'不及格');
        console.log(2,arr3map2);


        //2.reduce,返回1个结果,求聚合函数等
        //计算平均值
        let arr3reduce = arr3.reduce(function (tmp,item,index) {    //补充,4个扩展方法都有隐藏参数index
            // 参数解释:
            // tmp:上一次的结果(如果是首次则为第一个数的值)
            // item:当前的值
            // index:第几次,从1开始


            //如果是最后一次
            if (arr3.length-1 === index) {
                console.log('length',arr3.length-1);    //4
                console.log('index',index);             //4
                return (tmp + item)/arr3.length;        //3
            } else {
                return (tmp + item);
            }
        });
        alert(arr3reduce)

        //3.filter,过滤结果
        //获取偶数
        let arr3filter = arr3.filter(item => item % 2 === 0);   //通过布尔值来决定是否添加结果
        alert(arr3filter);


        //4.forEach 遍历
        arr3.forEach((item,index)=>{
           console.log('No',index+1, ' is ',item);
            alert(`No${index+1} is ${item}`)    //`xxx`:字符串模板,类似于插值表达式;注意不是单引号' 而是重音符 `
        });


        //==================================================
        //字符串相关
        //startsWith,endsWith       注意都有s

        let url = 'https://cn.bing.com/';
        if (url.startsWith('https://')) alert('starts with \'https://\'');

        let email = 'abc@gmail.com';
        if (email.endsWith('.com')) alert('ends with \'.com\'');


        //字符串模板
        //过去的写法
        let title = 'title';
        let str = '<div>\
                <h1>'+title+'</h1>\
                </div>';

        console.log(str);
        //使用字符串模板后的写法
        let newStr =`<div>
            <h1>${title}</h1>
            </div>
        `;
        console.log(newStr);

        //==================================================
        //JSON
        //标准的JSON写法
        let standardJson = {"a":"1","b":"2"};
        //但在js中可以使用简写来表示
        let  easyJson = {a:1,b:2,name:'json'};

        //stringify,让json转换为字符串,显示的是标准字符串
        alert(JSON.stringify(easyJson));
        console.log(JSON.stringify(easyJson));

        //解析字符串为json,中间的字符串必须是以标准格式!
        let myJson = JSON.parse('{"a":1,"b":2,"name":"json"}');
        console.log(myJson); //{a: 1, b: 2, name: "json"}
    </script>
</head>


<body>
    <input type="button" value="btn1">
    <input type="button" value="btn2">
    <input type="button" value="btn3">



<!--告知浏览器按照js来执行解释-->
<script type="text/javascript">

</script>



</body>
</html>



